[XEND] Add simple VCPUs, VBDs, VIFs statistics monitoring
authorAlastair Tse <atse@xensource.com>
Wed, 24 Jan 2007 12:09:41 +0000 (12:09 +0000)
committerAlastair Tse <atse@xensource.com>
Wed, 24 Jan 2007 12:09:41 +0000 (12:09 +0000)
Keep track of xentop like statistics to expose through the Xen API

Signed-off-by: Alastair Tse <atse@xensource.com>
tools/python/scripts/xapi.py
tools/python/xen/xend/XendDomainInfo.py
tools/python/xen/xend/XendNode.py

index 9bc3b507b871c35f520b88db25aba056bc122789..133bbfd12da47ecd0cd36692477e676458d7d0e1 100644 (file)
@@ -200,6 +200,12 @@ def xapi_host_info(*args):
         print HOST_INFO_FORMAT % ('VMs', len(hostinfo['resident_VMs']))
         print HOST_INFO_FORMAT % ('UUID', host)        
 
+        for host_cpu_uuid in hostinfo['host_CPUs']:
+            host_cpu = execute(server.host_cpu.get_record, session,
+                               host_cpu_uuid)
+            print 'CPU %s Util: %.2f' % (host_cpu['number'],
+                                         float(host_cpu['utilisation']))
+        
 def xapi_host_set_name(*args):
     if len(args) < 1:
         raise OptionError("No hostname specified")
index 554ce9adca1d6a575eca5585a443ae1229f8e210..76a4c11d1a41662bd765a29462cd4bc61f69cfc6 100644 (file)
@@ -2052,10 +2052,29 @@ class XendDomainInfo:
                     # handle that properly.
 
             config['MTU'] = 1500 # TODO
-            config['io_read_kbs'] = 0.0
-            config['io_write_kbs'] = 0.0
+            
+            if self.state not in (XEN_API_VM_POWER_STATE_HALTED,):
+                xennode = XendNode.instance()
+                rx_bps, tx_bps = xennode.get_vif_util(self.domid, devid)
+                config['io_read_kbs'] = rx_bps/1024
+                config['io_write_kbs'] = tx_bps/1024
+            else:
+                config['io_read_kbs'] = 0.0
+                config['io_write_kbs'] = 0.0                
 
         if dev_class == 'vbd':
+
+            if self.state not in (XEN_API_VM_POWER_STATE_HALTED,):
+                controller = self.getDeviceController(dev_class)
+                devid, _1, _2 = controller.getDeviceDetails(config)
+                xennode = XendNode.instance()
+                rd_blkps, wr_blkps = xennode.get_vbd_util(self.domid, devid)
+                config['io_read_kbs'] = rd_blkps
+                config['io_write_kbs'] = wr_blkps
+            else:
+                config['io_read_kbs'] = 0.0
+                config['io_write_kbs'] = 0.0                
+            
             config['VDI'] = config.get('VDI', '')
             config['device'] = config.get('dev', '')
             if ':' in config['device']:
@@ -2068,8 +2087,7 @@ class XendDomainInfo:
 
             config['driver'] = 'paravirtualised' # TODO
             config['image'] = config.get('uname', '')
-            config['io_read_kbs'] = 0.0
-            config['io_write_kbs'] = 0.0
+
             if config.get('mode', 'r') == 'r':
                 config['mode'] = 'RO'
             else:
@@ -2088,14 +2106,12 @@ class XendDomainInfo:
             raise XendError('Invalid property for device: %s' % field)
 
     def get_vcpus_util(self):
-        # TODO: this returns the total accum cpu time, rather than util
-        # TODO: spec says that key is int, however, python does not allow
-        #       non-string keys to dictionaries.
         vcpu_util = {}
+        xennode = XendNode.instance()
         if 'vcpus_number' in self.info and self.domid != None:
             for i in range(0, self.info['vcpus_number']):
-                info = xc.vcpu_getinfo(self.domid, i)
-                vcpu_util[str(i)] = info['cpu_time']/1000000000.0
+                util = xennode.get_vcpu_util(self.domid, i)
+                vcpu_util[str(i)] = util
                 
         return vcpu_util
 
index 30953f6a5305e306816849df1366db5e612a63d5..03f2915221d7cc6457ecf628fd09ced7c767e4af 100644 (file)
@@ -30,6 +30,7 @@ from xen.xend.XendLogging import log
 from xen.xend.XendPIF import *
 from xen.xend.XendNetwork import *
 from xen.xend.XendStateStore import XendStateStore
+from xen.xend.XendMonitor import XendMonitor
 
 class XendNode:
     """XendNode - Represents a Domain 0 Host."""
@@ -46,6 +47,8 @@ class XendNode:
         
         self.xc = xen.lowlevel.xc.xc()
         self.state_store = XendStateStore(xendoptions().get_xend_state_path())
+        self.monitor = XendMonitor()
+        self.monitor.start()
 
         # load host state from XML file
         saved_host = self.state_store.load_state('host')
@@ -285,8 +288,16 @@ class XendNode:
             raise XendError('Invalid CPU Reference')        
             
     def get_host_cpu_load(self, host_cpu_ref):
-        return 0.0
+        host_cpu = self.cpus.get(host_cpu_ref)
+        if not host_cpu:
+            return 0.0
+
+        vcpu = int(host_cpu['number'])
+        cpu_loads = self.monitor.get_domain_vcpus_util()
+        if 0 in cpu_loads and vcpu in cpu_loads[0]:
+            return cpu_loads[0][vcpu]
 
+        return 0.0
 
     #
     # Network Functions
@@ -397,6 +408,34 @@ class XendNode:
     def xendinfo(self):
         return [['xend_config_format', 3]]
 
+    #
+    # utilisation tracking
+    #
+
+    def get_vcpu_util(self, domid, vcpuid):
+        cpu_loads = self.monitor.get_domain_vcpus_util()
+        if domid in cpu_loads:
+            return cpu_loads[domid].get(vcpuid, 0.0)
+        return 0.0
+
+    def get_vif_util(self, domid, vifid):
+        vif_loads = self.monitor.get_domain_vifs_util()
+        if domid in vif_loads:
+            return vif_loads[domid].get(vifid, (0.0, 0.0))
+        return (0.0, 0.0)
+
+    def get_vbd_util(self, domid, vbdid):
+        vbd_loads = self.monitor.get_domain_vbds_util()
+        if domid in vbd_loads:
+            return vbd_loads[domid].get(vbdid, (0.0, 0.0))
+        return (0.0, 0.0)
+
+    def get_pif_util(self, pifid):
+        pifs_util = self.monitor.get_pifs_util()
+        if pifid in pifs_util:
+            return pifs_util[pifid]
+        return (0.0, 0.0)
+
     # dictionary version of *info() functions to get rid of
     # SXPisms.
     def nodeinfo_dict(self):